#include "lead_zeros.h"

static const uint8_t CntLeadZerosTbl[256] = {                                       /* Data vals :                      */
/*   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   */
    8u,  7u,  6u,  6u,  5u,  5u,  5u,  5u,  4u,  4u,  4u,  4u,  4u,  4u,  4u,  4u,  /*   0x00 to 0x0F                   */
    3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  /*   0x10 to 0x1F                   */
    2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  /*   0x20 to 0x2F                   */
    2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  /*   0x30 to 0x3F                   */
    1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  /*   0x40 to 0x4F                   */
    1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  /*   0x50 to 0x5F                   */
    1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  /*   0x60 to 0x6F                   */
    1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  /*   0x70 to 0x7F                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0x80 to 0x8F                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0x90 to 0x9F                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xA0 to 0xAF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xB0 to 0xBF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xC0 to 0xCF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xD0 to 0xDF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xE0 to 0xEF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u   /*   0xF0 to 0xFF                   */
};

uint32_t CntLeadZeros08(uint8_t val)
{
    uint32_t ix;
    uint32_t nbr_lead_zeros;

                                                                                /* Chk bits [07:00] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
    ix             = (uint32_t)(val >> 0u);                                     /* .. lookup tbl ix  = 'val' >>  0 bits */
    nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 0u);                      /* .. plus nbr msb lead zeros =  0 bits.*/

    return (nbr_lead_zeros);
}

uint32_t CntLeadZeros16(uint16_t val)
{
    uint32_t ix;
    uint32_t nbr_lead_zeros;

    if (val > 0x00FFu) {                                                        /* Chk bits [15:08] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
        ix             = (uint32_t)(val >> 8u);                                 /* .. lookup tbl ix  = 'val' >>  8 bits */
        nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 0u);                  /* .. plus nbr msb lead zeros =  0 bits.*/

    } else {                                                                    /* Chk bits [07:00] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
        ix             = (uint32_t)(val >> 0u);                                 /* .. lookup tbl ix  = 'val' >>  0 bits */
        nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 8u);                  /* .. plus nbr msb lead zeros =  8 bits.*/
    }

    return (nbr_lead_zeros);
}

uint32_t CntLeadZeros32(uint32_t val)
{
    uint32_t ix;
    uint32_t nbr_lead_zeros;

    if (val > 0x0000FFFFu) {
        if (val > 0x00FFFFFFu) {                                                /* Chk bits [31:24] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
            ix             = (uint32_t)(val >> 24u);                            /* .. lookup tbl ix  = 'val' >> 24 bits */
            nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 0u);              /* .. plus nbr msb lead zeros =  0 bits.*/

        } else {                                                                /* Chk bits [23:16] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
            ix             = (uint32_t)(val >> 16u);                            /* .. lookup tbl ix  = 'val' >> 16 bits */
            nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 8u);              /* .. plus nbr msb lead zeros =  8 bits.*/
        }

    } else {
        if (val > 0x000000FFu) {                                                /* Chk bits [15:08] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
            ix             = (uint32_t)(val >> 8u);                             /* .. lookup tbl ix  = 'val' >>  8 bits */
            nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 16u);             /* .. plus nbr msb lead zeros = 16 bits.*/

        } else {                                                                /* Chk bits [07:00] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
            ix             = (uint32_t)(val >> 0u);                             /* .. lookup tbl ix  = 'val' >>  0 bits */
            nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 24u);             /* .. plus nbr msb lead zeros = 24 bits.*/
        }
    }

    return (nbr_lead_zeros);
}

uint32_t CntLeadZeros64(uint64_t  val)
{
    uint32_t ix;
    uint32_t nbr_lead_zeros;

    if (val > 0x00000000FFFFFFFFu) {
        if (val > 0x0000FFFFFFFFFFFFu) {
            if (val > 0x00FFFFFFFFFFFFFFu) {                                    /* Chk bits [63:56] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
                ix             = (uint32_t)(val >> 56u);                        /* .. lookup tbl ix  = 'val' >> 56 bits */
                nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 0u);     		/* .. plus nbr msb lead zeros =  0 bits.*/

            } else {                                                            /* Chk bits [55:48] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
                ix             = (uint32_t)(val >> 48u);                        /* .. lookup tbl ix  = 'val' >> 48 bits */
                nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 8u);     		/* .. plus nbr msb lead zeros =  8 bits.*/
            }

        } else {
            if (val > 0x000000FFFFFFFFFFu) {                                    /* Chk bits [47:40] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
                ix             = (uint32_t)(val >> 40u);                        /* .. lookup tbl ix  = 'val' >> 40 bits */
                nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 16u);     	/* .. plus nbr msb lead zeros = 16 bits.*/

            } else {                                                            /* Chk bits [39:32] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
                ix             = (uint32_t)(val >> 32u);                        /* .. lookup tbl ix  = 'val' >> 32 bits */
                nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 24u);     	/* .. plus nbr msb lead zeros = 24 bits.*/
            }
        }

    } else {
        if (val > 0x000000000000FFFFu) {
            if (val > 0x0000000000FFFFFFu) {                                    /* Chk bits [31:24] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
                ix             = (uint32_t)(val >> 24u);                        /* .. lookup tbl ix  = 'val' >> 24 bits */
                nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 32u);     	/* .. plus nbr msb lead zeros = 32 bits.*/

            } else {                                                            /* Chk bits [23:16] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
                ix             = (uint32_t)(val >> 16u);                        /* .. lookup tbl ix  = 'val' >> 16 bits */
                nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 40u);     	/* .. plus nbr msb lead zeros = 40 bits.*/
            }

        } else {
            if (val > 0x00000000000000FFu) {                                    /* Chk bits [15:08] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
                ix             = (uint32_t)(val >>  8u);                        /* .. lookup tbl ix  = 'val' >>  8 bits */
                nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 48u);     	/* .. plus nbr msb lead zeros = 48 bits.*/

            } else {                                                            /* Chk bits [07:00] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
                ix             = (uint32_t)(val >>  0u);                        /* .. lookup tbl ix  = 'val' >>  0 bits */
                nbr_lead_zeros = (uint32_t)(CntLeadZerosTbl[ix] + 56u);     	/* .. plus nbr msb lead zeros = 56 bits.*/
            }
        }
    }

    return (nbr_lead_zeros);
}
